home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / std / c++ / 1051 < prev    next >
Encoding:
Text File  |  1996-08-06  |  7.6 KB  |  176 lines

  1. Path: engnews1.Eng.Sun.COM!taumet!clamage
  2. From: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
  3. Newsgroups: comp.std.c++
  4. Subject: Re: Array function params and const qualifier
  5. Date: 12 Apr 1996 15:30:08 GMT
  6. Organization: Comp Sci, University of Melbourne
  7. Approved: clamage@eng.sun.com (comp.std.c++)
  8. Message-ID: <4klir4$63e@mulga.cs.mu.OZ.AU>
  9. References: <4ke06a$rp3@mozart.wg.icl.co.uk> <4kjqqa$bol@engnews1.Eng.Sun.COM>
  10. NNTP-Posting-Host: taumet.eng.sun.com
  11. X-Nntp-Posting-Host: munta.cs.mu.oz.au
  12. Content-Length: 6778
  13. X-Lines: 151
  14. Originator: clamage@taumet
  15.  
  16. clamage@Eng.Sun.COM (Steve Clamage) writes:
  17.  
  18. >Adel El-Beik <A.El-Beik@man0506.wins.icl.co.uk> writes:
  19. >>I have a question concerning MSVC++ v.4.00 and the April DWP C++.
  20. >>
  21. >>The following code fails on MSVC++.  It doesn't like line labelled 1.
  22. >>It complains with 
  23. >>
  24. >>C:\array\array.cpp(16) : error C2664: 'func' : cannot convert parameter 1 
  25. >>from 'long [2][2]' to 'const long [][2]' (new behavior; please see help)
  26. >
  27. >You have run into effectively the same rule that prohibits implicit
  28. >conversion from "T**" to "const T**". That prohibition is not new,
  29. >but is in the ISO/ANSI C standard, and has not been changed, since
  30. >it would open a hole in the type system.
  31.  
  32. I suspect you are mistaken.  I believe Adel El-Beik has run into a bug
  33. in MSVC++, rather than any prohibition in the draft C++ standard.
  34. By my reading of the January 96 draft, I believe Adel El-Beik's code is
  35. well-formed (i.e. legal).
  36.  
  37. [moderator's note: I agree I was wrong. Sorry for the confusion. -sdc ]
  38.  
  39. >I believe the subject is covered in the comp.lang.c FAQ list.
  40.  
  41. The comp.lang.c FAQ list may cover the case of conversion from `T**' to
  42. `const T**' (although I couldn't find it in my old copy), but I'm sure
  43. it does not cover the case of conversion from `T[n][m]' to `const
  44. T(*)[m]', which I think is quite safe, and which is, I believe,
  45. permitted by the draft C++ standard.
  46.  
  47. Here's the code again, and an explanation of why I believe the code is legal.
  48.  
  49.     typedef long bar[2][2];
  50.     void func( const bar param ){}
  51.  
  52.     int main()
  53.     {
  54.         bar x;
  55.         func(x);        // rejected by 
  56.     }
  57.  
  58. The parameter of `func' is declared to have type `const bar', where
  59. `bar' is a typedef which names an array type.  Consulting 3.9.3/3,
  60.  
  61. |   3.9.3  CV-qualifiers                            [basic.type.qualifier]
  62. | 2 A  compound  type  (_basic.compound_)  is  not cv-qualified by the cv-
  63. |   qualifiers (if any) of the type from which it is compounded.  Any  cv-
  64. |   qualifiers that appear in an array declaration apply to the array ele-
  65. |   ment type, not the array type (_dcl.array_).
  66.  
  67. I think we can discern that the declared type of the
  68. parameter is "array [2] of array [2] of const long", rather than
  69. "const array [2] of array [2] of long".  The wording is quite vague [*]
  70. but I'm pretty sure that's the intent.  However, this is certainly
  71. the weakest step in my chain of reasoning.
  72.  
  73.     [*] What exactly is an "array declaration"?  Does `const bar'
  74.         count as one?  Does this rule apply recursively to arrays
  75.         of arrays?
  76.  
  77. Next, we need to consult 8.3.5/3.
  78.  
  79. |   8.3.5  Functions                                             [dcl.fct]
  80. | 3 [...] The type of a function is determined using the follow-
  81. |   ing rules.  The type of each parameter  is  determined  from  its  own
  82. |   decl-specifier-seq and declarator.  After determining the type of each
  83. |   parameter, any parameter of type "array of T" or  "function  returning
  84. |   T"  is adjusted to be "pointer to T" or "pointer to function returning
  85. |   T," respectively. [...]
  86.  
  87. In this case, the type of the parameter is adjusted from "array [2] of
  88. array [2] of const long" to "pointer to array [2] of const long".
  89.  
  90. So, we are trying to convert a value of type "array [2] of array [2] of long"
  91. to type "pointer to array [2] of const long".  According to 4/1,
  92.  
  93. |   4   Standard conversions                              [conv]
  94. | 1 Standard conversions are implicit  conversions  defined  for  built-in
  95. |   types.  The full set of such conversions is enumerated in this clause.
  96. |   A standard conversion sequence is a sequence of  standard  conversions
  97. |   in the following order:
  98. |   --Zero or one conversion from the following set: lvalue-to-rvalue con-
  99. |     version, array-to-pointer conversion, and  function-to-pointer  con-
  100. |     version.
  101. |   --Zero  or one conversion from the following set: integral promotions,
  102. |     floating point promotion, integral conversions, floating point  con-
  103. |     versions,   floating-integral   conversions,   pointer  conversions,
  104. |     pointer to member conversions, base class conversions,  and  boolean
  105. |     conversions.
  106. |   --Zero or one qualification conversion.
  107.  
  108. The first conversion we apply, then, is an array-to-pointer conversion.
  109. Consulting 4.2/1,
  110.  
  111. |   4.2  Array-to-pointer conversion                          [conv.array]
  112. | 1 An  lvalue or rvalue of type "array of N T" or "array of unknown bound
  113. |   of T" can be converted to an rvalue  of  type  "pointer  to  T."   The
  114. |   result is a pointer to the first element of the array.
  115.  
  116. we see that we can convert our value of type "array [2] of array[2] of long"
  117. to "pointer to array [2] of long".
  118.  
  119. We don't need to apply any conversions from the second set, but we
  120. do need to apply a qualification conversion before we can get to
  121. "pointer to array [2] of const long".  At first glance, 4.4/1
  122.  
  123. |   4.4  Qualification conversions                             [conv.qual]
  124. | 1 An  rvalue of type "pointer to cv1 T" can be converted to an rvalue of
  125. |   type "pointer to cv2 T" if "cv2 T" is more cv-qualified than  "cv1 T."
  126.  
  127. does not seem to be of any help, since the "const" is on the wrong
  128. side of the "array of".  However, this must be read in the context
  129. of 3.9.3/5.
  130.  
  131. |   3.9.3  CV-qualifiers                            [basic.type.qualifier]
  132. | 5 In this International Standard, the notation cv (or cv1,  cv2,  etc.),
  133. |   used  in  the description of types, represents an arbitrary set of cv-
  134. |   qualifiers, i.e., one of {const}, {volatile},  {const,  volatile},  or
  135. |   the  empty  set.  Cv-qualifiers applied to an array type attach to the
  136. |   underlying element type, so the notation "cv T," where T is  an  array
  137. |   type,  refers to an array whose elements are so-qualified.  Such array
  138. |   types can be said to be more (or less) cv-qualified than  other  types
  139. |   based on the cv-qualification of the underlying element types.
  140.  
  141. In our case, T is indeed an array type.  Reading 4.4/1 with `cv T'
  142. everywhere replaced with `array of cv T', as is required by 3.9.3,
  143. gives us the following rule:
  144.  
  145. ||  An  rvalue of type "pointer to array of cv1 T" can be converted to an
  146. ||  rvalue of type "pointer to array of cv2 T" if "cv2 T" is more
  147. ||  cv-qualified than  "cv1 T."
  148.  
  149. Applying this rule to the case in question, we can convert to "pointer
  150. to array [2] of long" to "pointer to array [2] of const long", since
  151. "const long" is more cv-qualified than "long".  At this point, we
  152. have shown that there exists a standard conversion sequence which converts
  153. the type of the actual parameter of `func' to the type of its formal
  154. parameter, and so it should be clear that the example is well-formed.
  155.  
  156. --
  157. Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
  158. WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
  159. PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
  160.  
  161.  
  162. [ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
  163. [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
  164. [ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
  165. [ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
  166. [ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]
  167.